package controllers.api;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import models.InternshipFamiliar;
import models.Profile;
import models.Subscriber;
import models.User;
import models.UserProfile;
import models.Profile.ProfileType;
import play.mvc.Router;
import play.mvc.Http.StatusCode;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import controllers.Check;
import controllers.Data;
import controllers.SecuredBaseController;
import controllers.Security;
import exceptions.ValidationException;

@Check(Security.ADMIN_ROLE)
public class Users extends ApiSecured {
	
	
	public static void list(Integer offset, Integer limit, String type) {
		if(offset == null) offset = 0;
		if(limit==null || limit > LIMIT || limit==0) {
			limit = LIMIT;
		}
		List<User> users = new ArrayList<User>();
		Integer count = 0;
		if(type == null || "".equals(type)) {
			count = User.count();
			if(count>0) users = User.paginate(User.all(), offset, limit);
		} else {
			if(ProfileType.ADMIN.getName().equals(type)) {
				count = User.countAdmins();
				if( count > 0 ) users.addAll(User.getAdmins(offset, limit));
				
			} else if(ProfileType.INTERNSHIP.getName().equals(type)) {
				count = User.countInternals();
				if(count>0) users.addAll(User.getInternals(offset, limit));
			} else if(ProfileType.FAMILIAR.getName().equals(type)) {
				count = User.countFamiliars();
				if(count>0) users.addAll(User.getFamiliars(offset, limit));
			} else {
				notFound();
			}
		}
		Data<User> data = new Data<User>();
		data.total = count;
		data.data = users;
		Type dataType = new TypeToken<Data<User>>(){}.getType();
		renderJSON(gson().toJson(data, dataType));
	}
	
	public static void get(Long id) {
		final User user = User.findById(id);
		if(user==null) {
			notFound();
		} 
		renderJSON(gson().toJson(user));
	}
	
	public static void add(JsonObject body) throws ValidationException {
		User user = new Gson().fromJson(body, User.class);
		validation.valid(user);
		if(validation.hasErrors()) {
			throw new ValidationException(validation.errors());
		}
		user.insert();
		UserProfile user_profile = new UserProfile(user,Profile.findByType(ProfileType.INTERNSHIP));
		user_profile.insert();
		response.status = StatusCode.CREATED;
		Map map = new HashMap();
		map.put("id", user.id);
		String url = Router.reverse("api.Users.get", map).url;// GET /clients/1541
		response.setHeader("location", url);
		renderJSON(gson().toJson(user));
	}
	
	public static void edit(Long id, JsonObject body) {
		User user = gson().fromJson(body, User.class);
		if(user==null) {
			notFound();
		}
		user.update();
		response.status = StatusCode.OK;
		Map map = new HashMap();
		map.put("id", user.id);
		String url = Router.reverse("api.Users.get", map).url;// GET /clients/1541
		response.setHeader("location", url);
	}
	
	public static void delete(Long id) {
		final User user = User.findById(id);
		if(user==null) {
			notFound();
		}
		InternshipFamiliar.delete(user);
		user.delete();
		response.status = StatusCode.NO_RESPONSE;
	}
	
	public static void listFamiliars(Long id, Integer offset, Integer limit) {
		if(offset == null) offset = 0;
		if(limit==null || limit > LIMIT || limit==0) {
			limit = LIMIT;
		}
		final User internal = User.findById(id);
		if(internal==null) {
			notFound();
		}
		Data<User> data = new Data<User>();
		data.total = InternshipFamiliar.countByInternship(internal);
		data.data  = new ArrayList<User>();
		data.data.addAll(InternshipFamiliar.paginateByInternship(InternshipFamiliar.findByInternship(internal), offset, limit));
		Type dataType = new TypeToken<Data<User>>(){}.getType();
		renderJSON(gson().toJson(data, dataType));
	}
	
	public static void addFamiliar(Long id, JsonObject body) throws ValidationException {
		User internal = User.findById(id);
		if(internal==null) {
			notFound();
		}
		User familiar = new Gson().fromJson(body, User.class);
		validation.valid(familiar);
		if(validation.hasErrors()) {
			throw new ValidationException(validation.errors());
		}
		familiar.insert();
		UserProfile user_profile = new UserProfile(familiar,
				Profile.findByType(Profile.ProfileType.FAMILIAR));
		user_profile.insert();
		InternshipFamiliar internshipFamiliar = new InternshipFamiliar(internal, familiar);
		internshipFamiliar.insert();
		response.status = StatusCode.CREATED;
		Map map = new HashMap();
		map.put("id", familiar.id);
		String url = Router.reverse("api.Users.get", map).url;// GET /users/1541
		response.setHeader("location", url);
		renderJSON(gson().toJson(familiar));
	}
	
	
	public static void profiles() {
		Data<String> data = new Data<String>();
		List<String> profileNames = new ArrayList<String>();
		data.total = Profile.count();
		data.data = profileNames;
		for(Profile profile : Profile.findAll()) {
			profileNames.add(profile.type.getName());
		}
		renderJSON(data);
	}
	
}